home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 112_01.zip / NROCMD.C < prev    next >
Text File  |  1993-06-19  |  12KB  |  643 lines

  1. /*
  2.  *    Command processor for NRO text processor
  3.  *
  4.  *    Stephen L. Browning
  5.  *    5723 North Parker Avenue
  6.  *    Indianapolis, Indiana 46220
  7.  */
  8.  
  9. #include "a:bdscio.h"
  10. #include "nro.h"
  11. #include "nrocom.c"
  12.  
  13. comand(p)
  14. char *p;
  15. {
  16.     int ct, val;
  17.     int spval;
  18.     int index;
  19.     char argtyp;
  20.     char name[MAXLINE];
  21.     char macexp[MXMLEN];
  22.  
  23.     ct = comtyp(p,macexp);
  24.     if (ct == UNKNOWN) {
  25.         printf("*** nro: unrecognized command %s\n",p);
  26.         return;
  27.     }
  28.     expesc(p,name);
  29.     val = getval(p,&argtyp);
  30.     switch (ct) {
  31.     case BO: /* bold face */
  32.         set(&dc.boval,val,argtyp,1,0,HUGE);
  33.         dc.cuval = dc.ulval = 0;
  34.         break;
  35.     case BP: /* begin page */
  36.         if(pg.lineno > 0) space(HUGE);
  37.         set(&pg.curpag,val,argtyp,pg.curpag+1,-HUGE,HUGE);
  38.         pg.newpag = pg.curpag;
  39.         break;
  40.     case BR: /* break */
  41.         brk();
  42.         break;
  43.     case BS: /* backspaces in output */
  44.         set(&dc.bsflg,val,argtyp,1,0,1);
  45.         break;
  46.     case CC: /* command character */
  47.         if (argtyp == '\r' || argtyp == '\n') dc.cmdchr = '.';
  48.         else dc.cmdchr = argtyp;
  49.         break;
  50.     case CE: /* center */
  51.         brk();
  52.         set(&dc.ceval,val,argtyp,1,0,HUGE);
  53.         break;
  54.     case CU: /* continuous underline */
  55.         set(&dc.cuval,val,argtyp,1,0,HUGE);
  56.         dc.ulval = dc.boval = 0;
  57.         break;
  58.     case DE: /* define macro */
  59.         defmac(p,&sofile[dc.flevel]);
  60.         break;
  61.     case EF: /* even footer */
  62.         gettl(p,pg.efoot,&pg.eflim[0]);
  63.         break;
  64.     case EH: /* even header */
  65.         gettl(p,pg.ehead,&pg.ehlim[0]);
  66.         break;
  67.     case EN: /* end macro definition */
  68.         puts("***nro: missing .de command\n");
  69.         break;
  70.     case FI: /* fill */
  71.         brk();
  72.         dc.fill = YES;
  73.         break;
  74.     case FO: /* footer */
  75.         gettl(p,pg.efoot,&pg.eflim[0]);
  76.         gettl(p,pg.ofoot,&pg.oflim[0]);
  77.         break;
  78.     case HE: /* header */
  79.         gettl(p,pg.ehead,&pg.ehlim[0]);
  80.         gettl(p,pg.ohead,&pg.ohlim[0]);
  81.         break;
  82.     case IN: /* indenting */
  83.         set(&dc.inval,val,argtyp,0,0,dc.rmval-1);
  84.         dc.tival = dc.inval;
  85.         break;
  86.     case JU: /* justify */
  87.         dc.juval = YES;
  88.         break;
  89.     case LS: /* line spacing */
  90.         set(&dc.lsval,val,argtyp,1,1,HUGE);
  91.         break;
  92.     case M1: /* set topmost margin */
  93.         set(&pg.m1val,val,argtyp,2,0,HUGE);
  94.         break;
  95.     case M2: /* set second top margin */
  96.         set(&pg.m2val,val,argtyp,2,0,HUGE);
  97.         break;
  98.     case M3: /* set first bottom margin */
  99.         set(&pg.m3val,val,argtyp,2,0,HUGE);
  100.         pg.bottom = pg.plval - pg.m4val - pg.m3val;
  101.         break;
  102.     case M4: /* set bottom-most margin */
  103.         set(&pg.m4val,val,argtyp,2,0,HUGE);
  104.         pg.bottom = pg.plval - pg.m4val - pg.m3val;
  105.         break;
  106.     case MACRO: /* macro expansion */
  107.         maceval(p,macexp);
  108.         break;
  109.     case NE: /* need n lines */
  110.         brk();
  111.         if ((pg.bottom-pg.lineno+1) < (val*dc.lsval)) {
  112.             space(HUGE);
  113.         }
  114.         break;
  115.     case NF: /* no fill */
  116.         brk();
  117.         dc.fill = NO;
  118.         break;
  119.     case NJ: /* no justify */
  120.         dc.juval = NO;
  121.         break;
  122.     case NR: /* set number register */
  123.         p = skipwd(p);
  124.         p = skipbl(p);
  125.         if (!isalpha(*p)) {
  126.             puts("***nro: invalid or missing number register name\n");
  127.         }
  128.         else {
  129.             index = tolower(*p) - 'a';
  130.             p = skipwd(p);
  131.             val = getval(p,&argtyp);
  132.             set(&dc.nr[index],val,argtyp,0,-HUGE,HUGE);
  133.         }
  134.         break;
  135.     case OF: /* odd footer */
  136.         gettl(p,pg.ofoot,&pg.oflim[0]);
  137.         break;
  138.     case OH: /* odd header */
  139.         gettl(p,pg.ohead,&pg.ohlim[0]);
  140.         break;
  141.     case PC: /* page number character */
  142.         if (argtyp == '\r' || argtyp == '\n') dc.pgchr = EOS;
  143.         else dc.pgchr = argtyp;
  144.         break;
  145.     case PL: /* page length */
  146.         set(&pg.plval,val,argtyp,PAGELEN,
  147.             pg.m1val+pg.m2val+pg.m3val+pg.m4val+1,HUGE);
  148.         pg.bottom = pg.plval - pg.m3val - pg.m4val;
  149.         break;
  150.     case PO: /* page offset */
  151.         set(&pg.offset,val,argtyp,0,0,HUGE);
  152.         break;
  153.     case RM: /* right margin */
  154.         set(&dc.rmval,val,argtyp,PAGEWIDTH,dc.tival+1,HUGE);
  155.         break;
  156.     case SO: /* source file */
  157.         p = skipwd(p);
  158.         p = skipbl(p);
  159.         if (getwrd(p,name) == 0) break;
  160.         if (dc.flevel+1 >= NFILES) {
  161.             puts("***nro: .so commands nested too deeply\n");
  162.             exit(-1);
  163.         }
  164.         if (fopen(name,&sofile[dc.flevel+1]) == ERR) {
  165.             printf("***nro: unable to open %s\n",name);
  166.             exit(-1);
  167.         }
  168.         ++dc.flevel;
  169.         break;
  170.     case SP: /* space */
  171.         set(&spval,val,argtyp,1,0,HUGE);
  172.         space(spval);
  173.         break;
  174.     case TI: /* temporary indent */
  175.         brk();
  176.         set(&dc.tival,val,argtyp,0,0,dc.rmval);
  177.         break;
  178.     case UL: /* underline */
  179.         set(&dc.ulval,val,argtyp,0,1,HUGE);
  180.         dc.cuval = dc.boval = 0;
  181.         break;
  182.     }
  183. }
  184.  
  185.  
  186.  
  187. /*
  188.  *    convert ascii character to decimal.
  189.  */
  190.  
  191. atod(c)
  192. char c;
  193. {
  194.     return(((c < '0') || (c > '9')) ? -1 : c-'0');
  195. }
  196.  
  197.  
  198.  
  199. /*
  200.  *    end current filled line
  201.  */
  202.  
  203. brk()
  204. {
  205.     if(co.outp > 0) {
  206.         co.outbuf[co.outp] = '\r';
  207.         co.outbuf[co.outp + 1] = '\n';
  208.         co.outbuf[co.outp + 2] = EOS;
  209.         put(co.outbuf);
  210.     }
  211.     co.outp = 0;
  212.     co.outw = 0;
  213.     co.outwds = 0;
  214. }
  215.  
  216.  
  217. /*
  218.  *    Collect macro definition from input stream
  219.  */
  220.  
  221. colmac(p,d,i)
  222. char *p, d[];
  223. int i;
  224. {
  225.     while (*p != EOS) {
  226.         if (i >= MXMLEN-1) {
  227.             d[i-1] = EOS;
  228.             return(ERR);
  229.         }
  230.         d[i++] = *p++;
  231.     }
  232.     d[i] = EOS;
  233.     return(i);
  234. }
  235.  
  236.  
  237.  
  238.  
  239. /*
  240.  *    decodes nro command and returns its associated
  241.  *    value.
  242.  */
  243.  
  244. comtyp(p,m)
  245. char *p;
  246. char *m;
  247. {
  248.     char c1, c2;
  249.     char macnam[MNLEN];
  250.     char *s;
  251.  
  252.     p++;
  253.     /*
  254.     *    First check to see if the command is a macro.
  255.     *    If it is, truncate to two characters and return
  256.     *    expansion in m.  Note that upper and lower case
  257.     *    characters are handled differently for macro names,
  258.     *    but not for normal command names.
  259.     */
  260.     getwrd(p,macnam);
  261.     macnam[2] = EOS;
  262.     if ((s = getmac(macnam)) != NULL) {
  263.         strcpy(m,s);
  264.         return(MACRO);
  265.     }
  266.     c1 = tolower(*p++);
  267.     c2 = tolower(*p);
  268.     if (c1 == 'b' && c2 == 'o') return(BO);
  269.     if (c1 == 'b' && c2 == 'p') return(BP);
  270.     if (c1 == 'b' && c2 == 'r') return(BR);
  271.     if (c1 == 'b' && c2 == 's') return(BS);
  272.     if (c1 == 'c' && c2 == 'c') return(CC);
  273.     if (c1 == 'c' && c2 == 'e') return(CE);
  274.     if (c1 == 'c' && c2 == 'u') return(CU);
  275.     if (c1 == 'd' && c2 == 'e') return(DE);
  276.     if (c1 == 'e' && c2 == 'f') return(EF);
  277.     if (c1 == 'e' && c2 == 'h') return(EH);
  278.     if (c1 == 'e' && c2 == 'n') return(EN);
  279.     if (c1 == 'f' && c2 == 'i') return(FI);
  280.     if (c1 == 'f' && c2 == 'o') return(FO);
  281.     if (c1 == 'h' && c2 == 'e') return(HE);
  282.     if (c1 == 'i' && c2 == 'n') return(IN);
  283.     if (c1 == 'j' && c2 == 'u') return(JU);
  284.     if (c1 == 'l' && c2 == 's') return(LS);
  285.     if (c1 == 'm' && c2 == '1') return(M1);
  286.     if (c1 == 'm' && c2 == '2') return(M2);
  287.     if (c1 == 'm' && c2 == '3') return(M3);
  288.     if (c1 == 'm' && c2 == '4') return(M4);
  289.     if (c1 == 'n' && c2 == 'e') return(NE);
  290.     if (c1 == 'n' && c2 == 'f') return(NF);
  291.     if (c1 == 'n' && c2 == 'j') return(NJ);
  292.     if (c1 == 'n' && c2 == 'r') return(NR);
  293.     if (c1 == 'o' && c2 == 'f') return(OF);
  294.     if (c1 == 'o' && c2 == 'h') return(OH);
  295.     if (c1 == 'p' && c2 == 'c') return(PC);
  296.     if (c1 == 'p' && c2 == 'l') return(PL);
  297.     if (c1 == 'p' && c2 == 'o') return(PO);
  298.     if (c1 == 'r' && c2 == 'm') return(RM);
  299.     if (c1 == 's' && c2 == 'o') return(SO);
  300.     if (c1 == 's' && c2 == 'p') return(SP);
  301.     if (c1 == 't' && c2 == 'i') return(TI);
  302.     if (c1 == 'u' && c2 == 'l') return(UL);
  303.     return(UNKNOWN);
  304. }
  305.  
  306.  
  307.  
  308. /*
  309.  *    convert string to decimal.
  310.  *    processes only positive values.
  311.  */
  312.  
  313. ctod(p)
  314. char *p;
  315. {
  316.     int val, d;
  317.  
  318.     val = 0;
  319.     while(*p != EOS) {
  320.         d = atod(*p++);
  321.         if(d == -1) return(val);
  322.         val = 10 * val + d;
  323.     }
  324.     return(val);
  325. }
  326.  
  327.  
  328. /*
  329.  *    Define a macro
  330.  */
  331.  
  332. defmac(p,infp)
  333. char *p;
  334. struct _buf *infp;
  335. {
  336.     int i;
  337.     char name[MNLEN];
  338.     char defn[MXMLEN];
  339.     char *q;
  340.  
  341.     q = skipwd(p);
  342.     q = skipbl(q);
  343.     i = getwrd(q,name);
  344.     if (!isalpha(*name)) {
  345.         puts("***nro: missing or illegal macro definition name\n");
  346.         exit(-1);
  347.     }
  348.     if (i > 2) name[2] = EOS;
  349.     i = 0;
  350.     while (getlin(p,infp) != EOF) {
  351.         if (p[0] == dc.cmdchr && tolower(p[1]) == 'e' && tolower(p[2]) == 'n') {
  352.             break;
  353.         }
  354.         if ((i = colmac(p,defn,i)) == ERR) {
  355.             puts("***nro: macro definition too long\n");
  356.             exit(-1);
  357.         }
  358.     }
  359.     if (putmac(name,defn) == ERR) {
  360.         puts("***nro: macro definition table full\n");
  361.         exit(-1);
  362.     }
  363. }
  364.  
  365.  
  366. /*
  367.  *    Expand escape sequences
  368.  */
  369.  
  370. expesc(p,q)
  371. char *p;
  372. char *q;
  373. {
  374.     char *s, *t;
  375.  
  376.     s = p;
  377.     t = q;
  378.     while (*s != EOS) {
  379.         if (*s != '@') {
  380.             *t++ = *s++;
  381.         }
  382.         else if (*(s+1) == '@') {
  383.             *t++ = *s++;
  384.             ++s;
  385.         }
  386.         else if (tolower(*(s+1)) == 'n' && isalpha(*(s+2))) {
  387.             s += 2;
  388.             t += itoda(dc.nr[tolower(*s)-'a'],t,6) - 1;
  389.             ++s;
  390.         }
  391.         else {
  392.             *t++ = *s++;
  393.         }
  394.     }
  395.     *t = EOS;
  396.     strcpy(p,q);
  397. }
  398.  
  399.  
  400.  
  401. /*
  402.  *    Get macro definition from table
  403.  */
  404.  
  405. char *getmac(name)
  406. char *name;
  407. {
  408.     int i;
  409.  
  410.     for (i = mac.lastp; i >= 0; --i) {
  411.         if (!strcmp(name,mac.mnames[i])) {
  412.             return(mac.mnames[i] + 3);
  413.         }
  414.     }
  415.     return(NULL);
  416. }
  417.  
  418.  
  419.  
  420.  
  421. /*
  422.  *    get header or footer title
  423.  */
  424.  
  425. gettl(p,q,limit)
  426. char *p;
  427. char *q;
  428. int limit[];
  429. {
  430.     p = skipwd(p);
  431.     p = skipbl(p);
  432.     strcpy(q,p);
  433.     limit[LEFT] = dc.inval;
  434.     limit[RIGHT] = dc.rmval;
  435. }
  436.  
  437.  
  438.  
  439. /*
  440.  *    retrieves optional argument following nro command.
  441.  *    returns positive integer value with sign (if any)
  442.  *    saved in character addressed by p_argt.
  443.  */
  444.  
  445. getval(p,p_argt)
  446. char *p;
  447. char *p_argt;
  448. {
  449.     p = skipwd(p);
  450.     p = skipbl(p);
  451.     *p_argt = *p;
  452.     if((*p == '+') || (*p == '-')) ++p;
  453.     return(ctod(p));
  454. }
  455.  
  456.  
  457. /*
  458.  *    Evaluate macro expansion
  459.  */
  460.  
  461. maceval(p,m)
  462. char *p;
  463. char m[];
  464. {
  465.     int i, j;
  466.     char *argp[10];
  467.     char c;
  468.  
  469.     *p++ = EOS;        /* replace command char with EOS */
  470.     /*
  471.     *    initialize argp array to substitute command
  472.     *    string for any undefined argument
  473.     */
  474.     for (i=0; i<10; ++i) argp[i] = p;
  475.     p = skipwd(p);
  476.     *p++ = EOS;
  477.     for (i=0; i<10; ++i) {
  478.         p = skipbl(p);
  479.         if (*p == '\r' || *p == '\n' || *p == EOS) break;
  480.         if (*p == ''' || *p == '"') {
  481.             c = *p++;
  482.             argp[i] = p;
  483.             while (*p != c && *p != '\r' && *p != '\n' && *p != EOS) ++p;
  484.             *p++ = EOS;
  485.         }
  486.         else {
  487.             argp[i] = p;
  488.             p = skipwd(p);
  489.             *p++ = EOS;
  490.         }
  491.     }
  492.     for (i=strlen(m)-1; i>=0; --i) {
  493.         if (i > 0 && m[i-1] == '$') {
  494.             if (!isdigit(m[i])) {
  495.                 putbak(m[i]);
  496.             }
  497.             else {
  498.                 pbstr(argp[m[i]-'0']);
  499.                 --i;
  500.             }
  501.         }
  502.         else {
  503.             putbak(m[i]);
  504.         }
  505.     }
  506. }
  507.  
  508.  
  509. /*
  510.  *    Push back string into input stream
  511.  */
  512.  
  513. pbstr(p)
  514. char p[];
  515. {
  516.     int i;
  517.  
  518.     for (i=strlen(p)-1; i>=0; --i) {
  519.         putbak(p[i]);
  520.     }
  521. }
  522.  
  523.  
  524.  
  525. /*
  526.  *    Push character back into input stream
  527.  */
  528.  
  529. putbak(c)
  530. char c;
  531. {
  532.     if (mac.ppb < &mac.pbb[0]) {
  533.         mac.ppb = &mac.pbb[0];
  534.         *mac.ppb = c;
  535.     }
  536.     else {
  537.         if (mac.ppb >= &mac.pbb[MAXLINE-1]) {
  538.             puts("***nro: push back buffer overflow\n");
  539.             exit(-1);
  540.         }
  541.         *++mac.ppb = c;
  542.     }
  543. }
  544.  
  545.  
  546.  
  547.  
  548. /*
  549.  *    Put macro definition into table
  550.  */
  551.  
  552. putmac(name,p)
  553. char *name;
  554. char *p;
  555. {
  556.     if (mac.lastp >= MXMDEF) return(ERR);
  557.     if (mac.emb + strlen(name) + strlen(p) + 1 > &mac.mb[MACBUF]) {
  558.         return(ERR);
  559.     }
  560.     ++mac.lastp;
  561.     mac.mnames[mac.lastp] = mac.emb;
  562.     strcpy(mac.emb,name);
  563.     strcpy(mac.emb + strlen(name) + 1,p);
  564.     mac.emb += strlen(name) + strlen(p) + 2;
  565.     return(OK);
  566. }
  567.  
  568.  
  569.  
  570.  
  571. /*
  572.  *    set parameter and check range
  573.  */
  574.  
  575. set(param,val,type,defval,minval,maxval)
  576. int *param;
  577. int val;
  578. char type;
  579. int defval,minval,maxval;
  580. {
  581.     switch(type) {
  582.     case '\r':
  583.     case '\n':
  584.         *param = defval;
  585.         break;
  586.     case '+':
  587.         *param += val;
  588.         break;
  589.     case '-':
  590.         *param -= val;
  591.         break;
  592.     default:
  593.         *param = val;
  594.         break;
  595.     }
  596.     *param = min(*param,maxval);
  597.     *param = max(*param,minval);
  598. }
  599.  
  600.  
  601.  
  602. /*
  603.  *    skip blanks and tabs in character buffer.
  604.  *    return number of characters skipped.
  605.  */
  606.  
  607. char *skipbl(p)
  608. char *p;
  609. {
  610.     while (*p == ' ' || *p == '\t') ++p;
  611.     return(p);
  612. }
  613.  
  614.  
  615. /*
  616.  *    skip over word and punctuation
  617.  */
  618.  
  619. char *skipwd(p)
  620. char *p;
  621. {
  622.     while (*p != ' ' && *p != '\t' && *p != '\r' && *p != '\n' && *p != EOS)
  623.         ++p;
  624.     return(p);
  625. }
  626.  
  627.  
  628.  
  629. /*
  630.  *    space vertically n lines
  631.  */
  632.  
  633. space(n)
  634. int n;
  635. {
  636.     brk();
  637.     if (pg.lineno > pg.bottom) return;
  638.     if (pg.lineno == 0) phead();
  639.     skip(min(n,pg.bottom+1-pg.lineno));
  640.     pg.lineno += n;
  641.     if (pg.lineno > pg.bottom) pfoot();
  642. }
  643.